home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
gnu
/
ms-0_06.lha
/
mslaved-0.06
/
mslavedc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-30
|
7KB
|
269 lines
/* mslavedc.c - MandelSpawn computation server control program */
/* (named in accordance with timedc, etc.). */
/* This file is part of MandelSpawn, a parallel Mandelbrot program for
the X window system.
Copyright (C) 1990 Andreas Gustafsson
MandelSpawn is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 1,
as published by the Free Software Foundation.
MandelSpawn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License,
version 1, along with this program; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <signal.h>
/* The only system I know needs these is SCO Unix, which needs them to */
/* define FNDELAY. If they cause trouble with you system, remove them */
#include <sys/types.h>
#include <sys/file.h>
#include "ms_ipc.h"
#define RETRIES 5 /* how many times to retry getting a PID in ping() */
extern int errno; /* 4.3BSD needs this even when errno.h is included */
char *me; /* name of program */
int port=DEFAULT_PORT; /* UDP port */
char *command=NULL;
char *timeout_arg="-t900"; /* by default time out in 15 minutes */
char *nice_arg=NULL;
int kill_mode=0;
/* report a fatal error and exit */
error(s)
char *s;
{ fprintf(stderr, "%s: ", me);
perror(s);
exit(1);
}
/* Repeatedly send datagrams to "host" trying to find out the pid of */
/* the existing server, if any. Returns the pid or 0 if no response. */
int ping(host)
char *host;
{ int i;
int status;
WhoAreYouMessage out;
Message in;
int osock, isock;
struct sockaddr_in oname, iname, mname;
int mnamelen;
struct hostent *hp, *gethostbyname();
/* set up the output socket; use an arbitrary port */
osock=socket(AF_INET, SOCK_DGRAM, 0);
if(osock<0)
{ error("opening output socket");
}
hp=gethostbyname(host);
if(hp==0)
{ error("unknown host");
}
/* set up the destination address */
oname.sin_family=AF_INET;
oname.sin_port=htons(port);
bcopy(hp->h_addr, (char *)&oname.sin_addr, hp->h_length);
isock=socket(AF_INET, SOCK_DGRAM, 0);
if(isock<0)
{ error("opening input socket");
}
iname.sin_family=AF_INET;
iname.sin_addr.s_addr=INADDR_ANY;
iname.sin_port=0;
if(bind(isock, &iname, (int) sizeof(iname)))
{ error("binding input socket");
}
if(fcntl(isock, F_SETFL, FNDELAY) == -1)
{ error("unblocking socket");
}
mnamelen=sizeof(mname);
if(getsockname(isock, &mname, &mnamelen)== -1)
error("getsockname");
out.header.magic=htons(MAGIC);
out.header.version=htons(VERSION);
out.header.type=htons(WHO_R_U_MESSAGE);
out.port=mname.sin_port; /* in network byte order already */
for(i=0; i<RETRIES; i++)
{ int nbytes;
int fromlen;
if(sendto(osock, (char *)&out, sizeof(WhoAreYouMessage), 0,
(struct sockaddr *)&oname, sizeof(oname)) < 0)
error("sending pid inquiry message");
/* This previously used read(), but some non-BSD TCP/IP implementations */
/* don't allow it to be used with connectionless sockets. Also, */
/* while the Sun implementation does allow for a null pointer */
/* for the "from" argument in recvfrom(), the "fromlen" argument */
/* may not be a null pointer. */
nbytes = recvfrom(isock, (char *) &in, sizeof(in),
0, (struct sockaddr *) 0, &fromlen);
if(nbytes == 0
#ifdef EWOULDBLOCK
|| (nbytes == -1 && errno == EWOULDBLOCK)
#endif
)
{ /* no reply yet */
sleep(1);
}
else if(nbytes == -1)
{ error("receiving pid info");
}
else /* got a reply */
{ status=ntohs(in.iam.pid);
goto done;
}
}
status=0; /* unsuccessful */
done:
(void) close(osock);
(void) close(isock);
return(status);
}
/* Kill any server that is already active in this machine */
/* return 0 if successful kill, 1 if no response */
int murder()
{ int pid;
char my_name[256];
if(gethostname(my_name, sizeof(my_name)) == 1)
error("gethostname");
pid=ping(my_name); /* get pid of existing server, if any */
if(pid==0)
return(1); /* return failed exit status */
if(kill(pid, SIGTERM)== -1)
error("kill");
return(0);
}
/* Set up the file handles and exec an mslaved */
void birth()
{ int isock;
struct sockaddr_in iname;
int tty;
int i;
/* argument list for mslaved */
char *arglist[10]; /* more than enough */
char **a; /* pointer to the above */
/* set up the socket */
isock=socket(AF_INET, SOCK_DGRAM, 0);
if(isock<0)
{ error("opening socket");
}
iname.sin_family=AF_INET;
iname.sin_addr.s_addr=INADDR_ANY;
iname.sin_port=htons(port);
if(bind(isock, &iname, (int) sizeof(iname)) == -1)
{ /* probable cause of error is that the port is in use */
error("binding socket");
}
/* dup the newly-opened socket to stdin */
close(0);
dup(isock);
#ifdef TIOCNOTTY /* presumably BSD-like */
if((tty=open("/dev/tty", 0, 0)) != -1)
{ ioctl(tty, TIOCNOTTY, (struct sgttyb *) 0);
(void) close(tty);
}
else
{ if(setpgrp(0, 0))
error("setpgrp");
}
#else /* presumably SYSV-like */
setpgrp();
#endif
for(i=1; i<10; i++)
(void) close(i);
a = arglist;
*a++ = command;
if(timeout_arg)
*a++ = timeout_arg;
if(nice_arg)
*a++ = nice_arg;
*a++ = (char *) 0;
execvp(command, arglist);
exit(1); /* there's no good way to report errors here */
}
main(argc, argv)
int argc; char **argv;
{ char *s;
me=argv[0];
for(;s = *++argv, --argc;)
{ if(*s == '-')
switch(*++s)
{
case 'k': /* kill */
kill_mode++;
break;
case 'q': /* query */
{ int rpid=ping(++s);
if(rpid)
{ printf("%d\n", rpid);
exit(0);
}
else exit(1);
}
case 'n': /* nice */
nice_arg= s-1; /* include the "-n" */
break;
case 't':
timeout_arg= s-1; /* include the "-t" */
break;
case 'p': /* port */
port=atoi(++s);
break;
default:
goto usage;
}
else
{ command= s;
}
}
if(kill_mode)
exit(murder());
if(!command)
error("missing command");
switch(fork())
{ case -1:
error("fork");
case 0: /* child */
birth();
default: /* parent */
exit(0);
}
usage:
fprintf(stderr, "usage: %s [-k] [-q] [-nnice] [-ttimeout] [-pport]\n", me);
exit(1);
}